package com.cnebula.openapi.auth.service.impl;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import com.cnebula.openapi.auth.service.AuthCodeService;
import com.cnebula.openapi.auth.util.MD5Util;
import com.cnebula.openapi.auth.vo.AccessToken;
import com.cnebula.openapi.auth.vo.AuthCode;
import com.cnebula.openapi.auth.vo.User;

import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.core.logging.Logger;
import io.vertx.core.logging.LoggerFactory;
import io.vertx.redis.RedisClient;
import io.vertx.redis.RedisOptions;

@Deprecated
public class AuthCodeServiceImpl implements AuthCodeService {

	RedisClient redis;

	private static final long CODE_EXPIRE = 60 * 10000;
	
	private static final Logger log = LoggerFactory.getLogger(AuthCodeServiceImpl.class);


	public AuthCodeServiceImpl(Vertx vertx) {
		redis = RedisClient.create(vertx, new RedisOptions());
	}

	@Override
	public Future<AuthCode> create(String clientKey, String tenantId, User user, AccessToken accessToken) {

		Future<AuthCode> future = Future.future();
		String logTag = "create auth code";

		Map<String, String> params = new HashMap<String, String>();
		params.put("accessToken", accessToken.token);
		params.put("clientKey", clientKey);
		params.put("tenantId", tenantId);
		params.put("userId", user.userId);
		params.put("userName", user.userName);
		params.put("random", UUID.randomUUID().toString());
		
		String code = "";
		try {
			code = MD5Util.md5(params);
		} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
			log.error(logTag,e);
			future.fail(e);
		}
		AuthCode authCode = new AuthCode();
		authCode.code = code;
		authCode.clientKey = clientKey;
		authCode.user = user;
		authCode.tenantId = tenantId;
		authCode.accessToken = accessToken;
		redis.psetex(authCode.code, CODE_EXPIRE, authCode.toString(), r -> {
			if (r.succeeded()) {
				future.complete(authCode);
			} else {
				log.error(logTag,r.cause());
				future.fail(r.cause());
			}
		});
		return future;
	}

	@Override
	public Future<AuthCode> take(String code) {
		Future<AuthCode> future = Future.future();
		String logTag = "take auth code";
		redis.get(code, h -> {
			if (h.succeeded()) {
				String str = h.result();
				AuthCode result = null;
				if (str != null && !str.isEmpty()) {
					result = AuthCode.build(str);
					redis.del(code, d->{});
				}
				future.complete(result);
			} else {
				log.error(logTag,h.cause());
				future.fail(h.cause());
			}
		});

		return future;
	}

}
